/*!\ file Battleship.h
 * \ author CT Ortman / Matthew Richard
 * \ Latest Update: 4/15/13
 * \ Contains the various functions for the Battleship class
 */

 // Construct for the class, needs to know whether it is consructing the instance for Player 1 or not (important for how subsequent functions will act)
Battleship::Battleship(bool p1)
{
  // Initialize the board class
  board = new int**[10];
  for(int i = 0; i<10; i++)
  {
    board[i]=new int*[10];
	for (int j=0; j<10; j++)
	{
	  board[i][j]=new int[2];
	}
  }
  for(int i=0; i < 10; i++)
  {
    for(int j=0; j < 10; j++)
    {
      for(int k=0; k < 2; k++)
      {
        board[i][j][k] = 0;
      }
    }
  }
  
  // Assign the Player1 bool value to whatever was passed to the class
  player1 = p1;

  // Initialize the 5 ship lengths
  shipSize[0] = 2;
  shipSize[1] = 3;
  shipSize[2] = 3;
  shipSize[3] = 4;
  shipSize[4] = 5;
  
  // Have the player controlling the instance place his ship positions
  placeShips();
}

// Updates the board of this instance of the game from a board from a different instance passed to it
void Battleship::updateBoard(int*** grid )
{
  for(int i=0; i<10; i++)
  {
    for(int j=0; j<10; j++)
    {
      for(int k=0; k<2; k++)
      {
        board[i][j][k] = grid[i][j][k];
      }
    }
  }
}

// Update the half of the board of this instance of the game controlled by the opposing player
// This only has to be done once, after ship placement. Subsquent changes can merely pass the entire board using the updateBoard function
void Battleship::getPlacement(int*** grid )
{
  for(int i=0; i<10; i++)
  {
    for(int j=0; j<10; j++)
    {
      board[i][j][!player1] = grid[i][j][!player1];
    }
  }
}

// Returns the entire board of this instance of the game
int *** Battleship::giveBoard()
{
  return board;
}

// Takes a single, legal move in an attempt to attack the opposing player
int *** Battleship::takeTurn()
{
  // Print the up-to-date board and initialize temporary variables
  printBoard();
  int yCoor;
  int xCoor;
  bool validMove = false;
  
  while(!validMove) // Loop until the player selects a valid move
  {
    cout << "Enter the y coordinate of the square you would like to attack:";
    cin>>yCoor;
	cout << "Enter the x coordinate of the square you would like to attack:";
    cin>>xCoor;
	
    if((((0<=yCoor)&&(yCoor<=9))&&((0<=xCoor)&&(xCoor<=9)))&&(board[yCoor][xCoor][!player1] < 6)) // Conditions insuring the coordinates are between 0 and 9,
    {																							  //   and that the space has not already been attacked
      validMove = true;
    }
	else
	{
	  cout << "Invalid location" << endl;
	}
  }
  if(board[yCoor][xCoor][!player1]==0) // If the location has never been interacted with (thus is blank), change the target of the attack to a "Miss" 
  {
    board[yCoor][xCoor][!player1]=6;
	cout << "Miss" << endl;
  }
  else // If the location has been interacted with (and because of earlier error checking cannot be a miss or hit) it must be a ship, change the target 
  {    //    of the attack to a "Hit" 
    board[yCoor][xCoor][!player1]=7;
	cout << "Hit" << endl;
  }
  
  // Return the new board
  return board;
}

// Identifies whether the owner of this instance of the game has won or not
bool Battleship::winCondition()
{
  bool wonGame=true; // Assume the owner has won
  
  // If any space on the opposing player's side of the board is a ship, flag the owner as having not won
  for(int i=0; i<10; i++)
  {
    for(int j=0; j<10; j++)
	{
	  if((board[i][j][!player1]>0)&&(board[i][j][!player1]<6))
	  {
	    wonGame=false;
	  }
	}
  }
  return wonGame;
}

// Print the current state of the board for the owner of this instance of the game
void Battleship::printBoard()
{
  // Output the Enemy's side of the board first
  cout << "Y      Enemy Board" << endl;
  for(int i=0; i<10; i++)
  {
    cout << i << " ";
    for(int j=0; j<10; j++)
	{
	  if(board[i][j][!player1]<6) // If any space is a blank (a 0), or an unattacked ship space (1 through 5), identify it on the screen as a blank
	    cout << ".";
	  else if(board[i][j][!player1]==6)  // If the space is a 6, it is a miss
	    cout << "O";
	  else   // If it is nothing else, it must be a hit (a 7)
	    cout << "X";
	  cout << " ";
	}
	cout << endl;
  }
  cout << "  0 1 2 3 4 5 6 7 8 9 X" << endl;
  cout << endl;
  
  // Output the owner's side of the board
  cout << "Y      Your Board" << endl;
  for(int i=0; i<10; i++)
  {
    cout << i << " ";
    for(int j=0; j<10; j++)
	{
	  if(board[i][j][player1]==0)  // If the space hasn't been interacted with by the other player, it is a blank (0)
	    cout << ".";
	  else if(board[i][j][player1]<6) // If the space contains one of the owner's ships, print that ships numerical identifier (1 through 5)
	    cout << board[i][j][player1];
	  else if(board[i][j][player1]==6) // Else, identify the space as a miss or hit respectively
	    cout << "O";
	  else 
	    cout << "X";
	  cout << " ";
	}
	cout << endl;
  }
  cout << "  0 1 2 3 4 5 6 7 8 9 X" << endl;
  cout << endl;
}

// Private function used at the beginning of the owning player's instance of the game to place their ships
void Battleship::placeShips()
{
  // Initialize temporary variables
  int x1,x2,y1,y2;
  bool badMove=true; // Identifies whether a move was an invalid move or not
  
  // Output which player the current player is (if the value is true, it will output a "1", if it is false, it will output a "2"
  cout << "Placing ships for Player " << (player1+(!player1)*2) << endl;
  
  // Run 5 times, once for each ship
  for (int i = 0; i<5; i++)
  {
    // Print the board so the player can see the x/y grid, and begin by assuming the player has an invalid move (and therefore must be proved to be valid)
    printBoard();
	badMove=true;
	
	// Continue to loop until the player selects a valid move
    while(badMove)
	{
	  cout << "Placing boat of length " << shipSize[i] << endl;
	  cout << "Enter y coordinate of the first end of the boat:";
	  cin >> x1;
	  cout << "Enter x coordinate of the first end of the boat:";
	  cin >> y1;
	  cout << "Enter y coordinate of the other end of the boat:";
	  cin >> x2;
	  cout << "Enter x coordinate of the other end of the boat:";
	  cin >> y2;
	  
	  // Checks to see if the coordinates of the ship ends are between 0 and 9, and that the entire ship lies in either one row or one column. It cannot sit on a diagonal
	  if((0<(x1+1))&&(x1<10)&&(0<(x2+1))&&(x2<10)&&(0<(y1+1))&&(y1<10)&&(0<(y2+1))&&(y2<10)&&(!((x1==x2)&&(y1==y2))))
	  {
	    // Depending on whether it is sitting in a row or column, check to see if each space between the ends of ship in that row or column is occupied by
		//   anything other than a blank space (a 0)
	    if(x1==x2)
		{
		  if((y2-y1)==shipSize[i]-1)
		  {
		    badMove=false;
			for(int j=0; j<shipSize[i];j++)
			{
			  if(board[x1][y1+j][player1]!=0)
			    badMove=true;
			}
		  }
		  else if((y1-y2)==shipSize[i]-1)
		  {
		    badMove=false;
			for(int j=0; j<shipSize[i];j++)
			{
			  if(board[x1][y2+j][player1]!=0)
			    badMove=true;
			}
		  }
		}
	    else if(y1==y2)
		{
		  if((x2-x1)==shipSize[i]-1)
		  {
		    badMove=false;
			for(int j=0; j<shipSize[i];j++)
			{
			  if(board[x1+j][y1][player1]!=0)
			    badMove=true;
			}
		  }
		  else if((x1-x2)==shipSize[i]-1)
		  {
		    badMove=false;
			for(int j=0; j<shipSize[i];j++)
			{
			  if(board[x2+j][y2][player1]!=0)
			    badMove=true;
			}
		  }
		}
	  }
	  // Proceed to attempt to place the id of the ship in each space on the board, so long as the placement was identified as valid
	  if(!badMove)
	  {
	    if((y2-y1)==shipSize[i]-1)
		{
		  for(int j = 0; j<shipSize[i]; j++)
		    board[x1][y1+j][player1]=i+1;
		}
		if((y1-y2)==shipSize[i]-1)
		{
		  for(int j = 0; j<shipSize[i]; j++)
		    board[x1][y2+j][player1]=i+1;
		}
		if((x2-x1)==shipSize[i]-1)
		{
		  for(int j = 0; j<shipSize[i]; j++)
		    board[x1+j][y1][player1]=i+1;
		}
		if((x1-x2)==shipSize[i]-1)
		{
		  for(int j = 0; j<shipSize[i]; j++)
		    board[x2+j][y1][player1]=i+1;
		}
	  }
	  else
	    cout << "Invalid move" << endl;
	}
  }
}
